#pragma once
#include <condition_variable>
#include <regex>
#include <mutex>
#include <queue>
#include <functional>

#include "MessageSynthesisTool.hpp"
#include "../message/interface/MessageInterface.hpp"

namespace MessageSynthesisTool1 {

    template<typename MESSAGE_TYPE>
    class MessagePools;
    /**
     *
     * @tparam MESSAGE_TYPE
     */
    template<typename MESSAGE_TYPE>
    class MessageObjectPool {
    private:
        TYPE m_messageTYpe;

        std::queue<MessageInterface<TYPE>*> m_unusedPool;
        std::unordered_set<MessageInterface<TYPE>*> m_usedPool;
        std::mutex m_mutex;


        // 使用函数工厂来创建消息对象
        std::function<MessageInterface<TYPE>*()> m_creaObjectFun;

        int m_poolSize;

    private:
        /**
         *
         * @param quantity
         */
        void addMessageToPool(int quantity) {
            for (int i = 0; i < quantity; i++)
                this->m_unusedPool.emplace(this->m_creaObjectFun());
        }

        /**
         *
         * @param creaObjectFun
         * @param poolSize
         */
        MessageObjectPool(const std::function<MessageInterface<TYPE>*()>& creaObjectFun ,int poolSize = 20) {
            this->m_creaObjectFun = creaObjectFun;

            //先创建一个实例获取格式
            MessageInterface<TYPE>* message = this->m_creaObjectFun();
            this->m_messageTYpe = message->getType();
            //将创建的实例加入池中
            this->m_unusedPool.push(message);

            this->m_poolSize = poolSize;


            //初始化池由于已经将一个实例加入池中所以数量-1
            this->addMessageToPool(poolSize-1);
        }


        ~MessageObjectPool() {
            while (!this->m_unusedPool.empty()) {
                MessageInterface<TYPE>* messageObject = this->m_unusedPool.front();
                this->m_unusedPool.pop();
                delete messageObject;
            }

            for (auto& message : this->m_usedPool) {
                MessageInterface<TYPE>* messageObject = message;
                this->m_usedPool.erase(message);
                delete messageObject;
            }
        }


        /**
         *
         * @return
         */
        MessageInterface<TYPE>* acquireMessgeObject() {
            std::unique_lock<std::mutex> lock(this->m_mutex);

            //消息池已分配完，扩容消息池
            if (this->m_unusedPool.empty()) {
                int quantity = this->m_poolSize*0.5;
                this->addMessageToPool(quantity);
                this->m_poolSize+=quantity;
            }

            MessageInterface<TYPE>* message = this->m_unusedPool.front();
            this->m_unusedPool.pop();
            this->m_usedPool.insert(message);

            return message;
        }

    public:
        friend MessageObjectPool<MESSAGE_TYPE>;

    };


    /**
     *
     * @tparam MESSAGE_TYPE
     */
    template<typename MESSAGE_TYPE>
    class MessagePools {
    private:
        //检测消息格式的正则表达式
        static const std::regex checkMessagePattern;
        //提取键值对的表达式
        static const std::regex KVPattern;
        std::unordered_map<MESSAGE_TYPE,MessageObjectPool<MESSAGE_TYPE>*> m_messagesObjectsPools;

        int m_defaultPoolSize;

        static MessagePools<MESSAGE_TYPE>* singleton;

        static std::mutex singletonMutex;

    public:

        MessagePools& operator=(const MessagePools<MESSAGE_TYPE>&) = delete;
        MessagePools(MessagePools<MESSAGE_TYPE>&) = delete;


        /**
         *
         * @param defaultPoolSize
         * @return
         */
        MessagePools<MESSAGE_TYPE>* getSingleton(int defaultPoolSize = 20) {
            if (MessagePools<MESSAGE_TYPE>::singleton != nullptr) return MessagePools<MESSAGE_TYPE>::singleton;
            std::lock_guard<std::mutex> lock(MessagePools<MESSAGE_TYPE>::singletonMutex);
            if (MessagePools<MESSAGE_TYPE>::singleton != nullptr) return MessagePools<MESSAGE_TYPE>::singleton;
            MessagePools<MESSAGE_TYPE>::singleton = new MessagePools<MESSAGE_TYPE>(defaultPoolSize);
            return MessagePools<MESSAGE_TYPE>::singleton;
        }


        /**
         *
         * @tparam MESSAGE
         * @param messageStr
         * @param messagePointer
         * @return
         */
        template<typename MESSAGE>
        bool acquireMessge(std::string& messageStr, MESSAGE*& messagePointer) {
            if (!std::regex_search(messageStr,MessagePoolsTool<TYPE>::checkMessagePattern))
                return false;

            //提取键值对
            auto wordsBegin = std::sregex_iterator(messageStr.begin(),messageStr.end(),MessagePoolsTool<TYPE>::KVPattern);
            auto wordsEnd = std::sregex_iterator();
            std::unordered_map<std::string, std::string> keyValuePairs;
            for (std::sregex_iterator it = wordsBegin; it!=wordsEnd; ++it) {
                std::smatch match = *it;
                keyValuePairs[match[1]] = match[2];
            }

            //没有type键值对
            auto keyValuePairsIt = keyValuePairs.find("type");
            if (keyValuePairsIt == keyValuePairs.end()) return false;

            try {
                TYPE messageType = static_cast<TYPE>(std::stoi(keyValuePairsIt->second)); //调用该函数有异常可能

                //超出消息样式范围
                if (messageType >= TYPE::END || messageType <= TYPE::BEGIN)
                    return false;

                //寻找该类型的消息数组
                auto messagesObjectsPoolsIt = this->m_messagesObjectsPools.find(messageType);

                //不存在该类型消息池，则创建该类型消息池
                if (messagesObjectsPoolsIt == this->m_messagesObjectsPools.end()) {
                    // 使用正确的模板参数创建MessageObjectPool
                    auto createMessageObjectFun = []() {
                        return new MESSAGE();
                    };
                    auto pool = std::make_shared<MessageObjectPool>(createMessageObjectFun,this->m_defaultPoolSize);
                    messagesObjectsPoolsIt = this->m_messagesObjectsPools.emplace(messageType, pool).first;
                }

                //从池中获取Message
                MessageInterface<TYPE>* messageObject = messagesObjectsPoolsIt->second-> acquireMessgeObject();

                //将MessageObject类型转化成指定的消息类型
                messagePointer = static_cast<MESSAGE*>(messageObject);

                //通过键值对初始化消息
                messagePointer->initializetionByKeyValuePairs(keyValuePairs);

                std::cout << messagePointer << std::endl;

                return true;
            }
            catch (...){return false;}
        }


        /**
         *
         * @tparam MESSAGE
         * @param messagePointer
         */
        template<typename MESSAGE>
        void releaseMessage(MESSAGE* messagePointer) {
            auto messagesObjectsPoolsIt = this->m_messagesObjectsPools.find(messagePointer->getType());

            if (messagesObjectsPoolsIt == this->m_messagesObjectsPools.end()) return;

            //清除数据
            messagePointer->clear();

            messagesObjectsPoolsIt->second.get()->releaseMessageObeject(messagePointer);
        }

    private:


        /**
         *
         * @param defaultPoolSize
         */
        MessagePools(int defaultPoolSize = 20) {
            this->m_defaultPoolSize = defaultPoolSize;
        }
        ~MessagePools() {}
    };

    /**
     *
     * @tparam MESSAGE_TYPE
     */
    template<typename MESSAGE_TYPE>
    class MessageProcessor {

    };
};

template<typename MESSAGE_TYPE>
const std::regex MessageSynthesisTool1::MessagePools<MESSAGE_TYPE>::checkMessagePattern = std::regex(R"(^\s*\{\s*[^\s;:]+\s*:\s*[^;:]+(?:\s*;\s*[^\s;:]+\s*:\s*[^;:]+)*\s*\}\s*$)");

template<typename MESSAGE_TYPE>
const std::regex MessageSynthesisTool1::MessagePools<MESSAGE_TYPE>::KVPattern = std::regex(R"(([^\s;:{]+)\s*:\s*([^;}]+)\s*)");

template<typename MESSAGE_TYPE>
typename MessageSynthesisTool1::MessagePools<MESSAGE_TYPE>* MessageSynthesisTool1::MessagePools<MESSAGE_TYPE>::singleton = nullptr;

template<typename MESSAGE_TYPE>
std::mutex MessageSynthesisTool1::MessagePools<MESSAGE_TYPE>::singletonMutex;